package com.fxg.Util;

import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;

import java.util.Collections;

/**
 * redis分布式锁的工具类
 */
@Slf4j
public class RedisLockUtil {

    //使用这个key当锁
    private static String LOCK_KEY = "redis_lock";
    //key的持有时间
    private static long EXPIRE_TIME = 1;
    //即当key不存在时，我们进行set操作；若key已经存在，则不做任何操作；
    private static final String SET_IF_NOT_EXIST = "NX";
    //过期时间的单位，ex为秒，px为毫秒
    private static final String SET_WITH_EXPIRE_TIME = "ex";

    private static final Long RELEASE_SUCCESS = 1L;

    private static final String LOCK_SUCCESS = "OK";


    /**
     * 尝试获取分布式锁
     */
    public static boolean tryLock (String requestId) {
//        log.info(requestId+"尝试加锁");
        Jedis jedis = RedisHelper.INSTANCE.jedis();
        try {
            String result = jedis.set(LOCK_KEY, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, EXPIRE_TIME);
            if (LOCK_SUCCESS.equals(result)) {
//            log.info(requestId+"加锁成功");
                return true;
            }
//        log.info(requestId+"加锁失败");
            return false;
        } finally {
            jedis.close();
        }

    }

    /**
     * 释放锁
     */
    public static boolean tryUnlock (String requestId) {

//        log.info(requestId+"尝试释放锁");
        Jedis jedis = RedisHelper.INSTANCE.jedis();
        try {
            //先校验是不是这个线程上的锁，是的话就释放，校验+释放 两步操作，不是一个原子性操作，所以通过lua脚本将这两个操作变为一个原子性操作
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object result = jedis.eval(script, Collections.singletonList(LOCK_KEY), Collections.singletonList(requestId));

            if (RELEASE_SUCCESS.equals(result)) {
//            log.info(requestId+"释放锁成功");
                return true;
            }
            return false;
        } finally {
            jedis.close();
        }

    }




}
